define(function(require){

//常用的全局变量
window.$win = $(window)
window.$doc = $(document)
window.$body = $('body')
window.baidu = {} // baidu 作为全局变量，方便 cleanContent 内拿到 UE 对象
if(!SNB.currentUser){
  SNB.currentUser={
    isGuest:true
  }
}

Backbone.sync = function (method, model, options) {
  var getUrl = function(object) {
    if (!(object && object.url)) return null;
    return _.isFunction(object.url) ? object.url() : object.url;
  };

  var urlError = function() {
    throw new Error('A "url" property or function must be specified');
  };
  if (!options.url) {
    options.url = getUrl(model) || urlError();
  }
  options.dataType = 'jsonp'
  options.data = options.data || {}
  options.data.access_token = SNB.Util.getAccessToken()
  return $.ajax(options);
};
$.ajaxSetup({
  cache: false
});
$.ajaxSetup({
    type: 'POST',
    headers: { "cache-control": "no-cache" }
});

if( navigator.userAgent.match(/Android/i) ||
 navigator.userAgent.match(/webOS/i) ||
 navigator.userAgent.match(/iPad/i) ||
 navigator.userAgent.match(/iPhone/i) ||
 navigator.userAgent.match(/iPod/i)
 ) $.browser.isMobile = true;
if (navigator.userAgent.match(/iPad/i)) $.browser.isPad = true
if (!$.browser.isMobile && !$.browser.isPad) $.browser.isPC = true
$.browser.supportUpload = (function () {
  var ipt = document.createElement('input')
  ipt.setAttribute('type', 'file')
  return ipt.type != 'text' && !ipt.disabled
}())

;(function($) {
  if ($.browser.webkit) { $body.addClass('webkit') }
  if ($.browser.mozilla) { $body.addClass('moz') }
  if ($.browser.msie) { $body.addClass('ms') }
  if (typeof SNB == 'undefined') {
    SNB = {
      Views: {},
      Templates: {},
      Models: {}
    };
  }

  SNB.run = SNB.log = SNB.error = SNB.debug = function () {}
  if (SNB.env && SNB.env != 'production') { // 非 production 环境有 SNB.run()
    SNB.run = function () {
      /* 默认为 development 环境
      * SNB.run('test', function () ...) 在 test 环境运行
      * 在多个环境可以用 SNB.run(['test', 'development'], function () ...)
      * 或 SNB.run('test', 'development', function () ...)
      */
      var args = Array.prototype.slice.call(arguments)
        , envs = []
      func = args.pop()
      if (!args.length) envs = ['development']
      else if (typeof args[0] == 'string') envs = args
      else if (args[0] instanceof Array) envs = args[0]
      if (~_.indexOf(envs, SNB.env)) func()
    }
  }

  SNB.run('development', function () { // 仅 development 环境有 SNB.log/error/debug
    SNB.log = function (s) { window.console && console.log(s) }
    SNB.error = function (s) { window.console && console[console.error ? 'error' : 'log'](s) }
    SNB.debug = function (str) { window.console && SNB.error('DEBUG: ' + str) }
  })
  if (!window.console) { // 防止 IE8 报错
    window.console = { log: function () {} }
  }
  SNB.logger = function(data){
    if (typeof data == 'string') {
      data = {
        event: data,
        time: (new Date()).getTime() - WATCH.pageStart
      }
    }
    $.post("/service/logger", data)
  }
  if ($.cookie("xq_a_token")) {
    $.cookie("last_account", null, {path: '/'});
  }
  if(!SNB.get){
    SNB.get = function(url, data, callback, error_callback) {
      var dataType="json";
      if (typeof data == 'function') {
        error_callback = callback
        callback = data
        data = {}
      }
      if (data == '') {
        data = {}
      }
      data.access_token = SNB.Util.getAccessToken()
      if (url.search('http://api.xueqiu.com') == 0) {
        url = url.substr(21)
      };
      if(url.search('https://') == 0){
        dataType="jsonp";
      }
      if(location.host.match(/imeigu.com/i)){
        url = "http://xueqiu.com" + url;
        dataType="jsonp";
      }
      var xhr = $.ajax({
        url: url,
        data: data,
        type: "GET",
        dataType:dataType,
        success: function(ret){
          var suc_ret = typeof ret !== "object" ? $.parseJSON(ret) : ret;
          callback && callback(suc_ret)
        },
        error: function(ret) {
          var errorObj = ret.responseText;
          if(typeof errorObj !== "object"){
            errorObj = $.parseJSON(errorObj);
          }
          if (errorObj && errorObj.error_code == '400016' || errorObj && errorObj.error_code == '400013'){
            location.href = '/'
          }else if(errorObj && errorObj.error_code === "10022"){
            SNB.currentUser = {isGuest: true}
            SNB.Util.checkLogin(function(){
              SNB.get(url,data,callback,error_callback)
            })
            return;
          }
          error_callback && error_callback(errorObj);
        }
      })
      return xhr
    }
  }
  SNB.post = function(url, data, callback, error_callback) {
    if (typeof data == 'function') {
      callback = data
      error_callback = callback
      data = {}
    }
    data.access_token = SNB.Util.getAccessToken()
    data._ = new Date().getTime()
    return $.ajax({
      url: '/service/poster',
      data: {
        url: url,
        data: data
      },
      type: "POST",
      success: function(ret){
        if (typeof ret !== 'object') {
          ret = $.parseJSON(ret);
        }
        callback && callback(ret)
      },
      error: function(ret){
        var errorObj = ret.responseText;
        if(typeof errorObj !== "object"){
          errorObj = $.parseJSON(errorObj);
        }
        if(errorObj && errorObj.error_code === "10022"){
          SNB.currentUser = {isGuest: true}
          SNB.Util.checkLogin(function(){
            SNB.post(url,data,callback,error_callback)
          })
          return;
        }
        error_callback && error_callback(errorObj);
      }
    })
  }

  var origParse = Date.parse;
  Date.parse = function(date) {
    var timestamp = origParse(date),
    minutesOffset = 0,
    struct;
    if (isNaN(timestamp) && /\+|-/.test(date)) {
      date = date.replace(/(\+|-)/g, 'UTC$1');
      timestamp = origParse(date);
    }
    return timestamp;
  };
  (function() {
    this.getFullMonth = function() {
      var month = this.getMonth() + 1;
      month = month < 10 ? '0' + month: month;
      return month;
    };
    this.getFullDate = function() {
      var date = this.getDate();
      date = date < 10 ? '0' + date: date;
      return date;
    };
    this.getFullHours = function() {
      var h = this.getHours();
      h = h < 10 ? '0' + h: h;
      return h;
    };
    this.getFullMinutes = function() {
      var m = this.getMinutes() + 1;
      if (m == 60) {m = 59}
      m = m < 10 ? '0' + m: m;
      return m;
    };
  }).call(Date.prototype);

  $.extend({
    getParam: function(str) {
      var url = str || window.location.search
      url = url.indexOf('?') !== -1 ? url.substring(url.indexOf('?') + 1) : url;
      var urlParams = decodeURIComponent(url);

      if(urlParams == false | urlParams == '') return null;

      var pairs = urlParams.split("&");

      var keyValue_Collection = {};
      for(var value in pairs) {
        var equalsignPosition = pairs[value].indexOf("=");

        if (equalsignPosition == -1) {
          keyValue_Collection[ pairs[value] ] = ''; //you could change the value to true as per your needs
        } else {
          keyValue_Collection[ pairs[value].substring(0, equalsignPosition) ] = pairs[value].substr(equalsignPosition + 1);
        }
      }
      return keyValue_Collection;
    }
  })

  $.extend($.fn, {
      found: function(callback, notFoundCallback) {
        if (this.length) {
          var $this = $(this)
          callback.call($this, $this)
        } else if (notFoundCallback) {
          this.notFound(notFoundCallback)
        }
        return this
      }
    , notFound: function(callback) {
        if (!this.length) callback()
        return this
      }
    , findOrAppend: function(selector, template, locals, callback) {
        var $el = $.fn.find.call(this, selector)
        if ('function' === typeof locals) {
          callback = locals
          locals = {}
        }
        if (!$el.length) {
          locals = locals || {}
          $el = $('function' === typeof template ? template(locals) : template).appendTo(this)
          callback && callback.call($el, $el, true)
        } else {
          callback && callback.call($el, $el, false)
        }
        return this
      }
    , reverse: Array.prototype.reverse
  });

  SNB.Pager = function(page, maxPage, options) {
    var pagerHtml = "<div class='pager-wrapper'><ul class='pager'>",
      adjPager = "",
      lastPage = page - 2,
      more_query = "",
      params = $.getParam();
    page = typeof page === "string" ? parseInt(page) : page
    maxPage = typeof maxPage === "string" ? parseInt(maxPage) : maxPage
    if(typeof options !== "undefined"){
      _.map(options,function(val,key){
        params[key] = val
      })
    }
    if ($.isPlainObject(params)) {
      delete params.page;
      $.map(params, function(val, key){
        more_query += "&" + encodeURIComponent(key)+ '=' + encodeURIComponent(val);
      });
    }
    while (lastPage <= maxPage && ((lastPage - page) <= 2 || lastPage <= 5)) {
      if (lastPage > 0) {
        adjPager += "<li" + (lastPage === page ? " class='active'": "") + "><a data-page='" + lastPage + "' href='?page=" + lastPage + more_query+ "'>" + lastPage + "</a></li>";
      }

      lastPage ++;
    }
    if (page != 1) {
      pagerHtml += "<li class='last'><a data-page='" + (page - 1) + "' href='?page=" + (page - 1) + more_query+  "'><span>上一页</span><i></i></a></li>";
      if (page > 3) {
        pagerHtml += "<li><a data-page='" + 1 + "' href='?page=1" + more_query + "'>1</a></li>";
        if (page > 4) {
          pagerHtml += '<li>...</li>';
        }
      }
    }
    pagerHtml += adjPager;
    if (page != maxPage) {
      if ((page + 2) < maxPage) {
        if ((page + 3) < maxPage) {
          pagerHtml += "<li>...<li>";
        }
        if(lastPage-maxPage!==1){
          pagerHtml += "<li><a data-page='" + maxPage + "' href='?page=" + maxPage + more_query + "'>" + maxPage + "</a></li>";
        }
      }
      pagerHtml += "<li class='next'><a data-page='" + (page + 1) + "' href='?page=" + (page + 1) + more_query + "'><span>下一页</span><i></i></a></li>";
    }
    pagerHtml += "</ul></div>";
    return pagerHtml;
  };


  SNB.Util = {
    MAX_STATUS_WORDS: 140,
    MAX_LONG_STATUS_WORDS: 20000,
    MAX_DM_WORDS: 300,
    BBCODE_IMAGE_BASEURL: SNB.domain['static'] + "/images/face/",
    BBCODE_TO_TEXT: {},
    TEXT_TO_BBCODE: {},
    BBCODE_MAPPING: [['01smile', '[微笑]'], ['02smile-big', '[呵呵]'], ['03laugh', '[哈哈]'], ['04clap', '[鼓掌]'], ['05confused', '[困惑]'], ['06sad', '[难过]'], ['07angry', '[生气]'], ['08cute', '[可爱]'], ['09act-up', '[调皮]'], ['10sweat', '[汗]'], ['11good', '[赞]'], ['12bad', '[贬]'], ['13love', '[爱]'], ['14love-over', '[心碎]'], ['15rose', '[献花]'], ['16rose-dead', '[凋谢]'], ['17in-love', '[色]'], ['18kiss', '[亲亲]'], ['19poop', '[屎]'], ['20victory', '[胜利]'], ['21desire', '[仰慕]'], ['22moneymouth', '[贪财]'], ['23quiet', '[无语]'], ['24secret', '[秘密]'], ['25shut-mouth', '[闭嘴]'], ['26shame', '[害羞]'], ['27sick', '[讨厌]'], ['28dazed', '[晕]'], ['29question', '[疑问]'], ['30sleepy', '[困]'], ['31arrogant', '[傲慢]'], ['32curse', '[诅咒]'], ['33crying', '[哭]'], ['34disapointed', '[失望]'], ['35embarrassed', '[尴尬]'], ['36dont-know', '[不知道]'], ['37handshake', '[握手]'], ['38struggle', '[挣扎]'], ['39thinking', '[思考]'], ['40tongue', '[吐舌]'],
['20smile-smile', '[笑]'],
['21lol', '[大笑]'],
['14guzhang', '[鼓鼓掌]'],
['19qiaopi', '[俏皮]'],
['08jiayou', '[加油]'],
['23earn', '[赚大了]'],
['11niubi', '[牛]'],
['24angry', '[怒了]'],
['25weep', '[哭泣]'],
['09lose', '[亏大了]'],
['26sleepy', '[困顿]'],
['18shiwang', '[好失望]'],
['10han', '[滴汗]'],
['13why', '[为什么]'],
['16guile', '[跪了]'],
['12hand', '[摊手]'],
['22buxie', '[不屑]'],
['15xunka', '[好逊]'],
['43kunhuo', '[好困惑]'],
['44sikao', '[想一下]'],
['45aoman', '[傲]'],
['17shutup', '[不说了]'],
['27weiguan', '[围观]'],
['03zan', '[很赞]'],
['04bian', '[不赞]'],
['05woshou', '[赞成]'],
['40cheers', '[干杯]'],
['36heart', '[心心]'],
['37heartbreak', '[心碎了]'],
['38flower', '[献花花]'],
['39shit', '[一坨屎]'],
['41full', '[满仓]'],
['42empty', '[空仓]'],
['34reverse', '[复盘]'],
['35bottom', '[抄底]'],
['33nengliquan', '[能力圈]'],
['29put', '[看空]'],
['30call', '[看多]'],
['31add', '[加仓]'],
['32reduce', '[减仓]'],
['01buy', '[买入]'],
['02sell', '[卖出]'],
['06maogugu', '[毛估估]'],
['07deal', '[成交]'],
['28moat', '[护城河]']
],
    personalityResult: function(resultText) {
      var w = [10, 5, 10, 10, 10, 10, 10, 10, 5, 20];
      var result = _.map(resultText.replace(/^\s+|\s+$/g, '').split(''), function(l) {
        return parseInt(l, 36)-10;
      });
      var s = _.reduce(w, function (p, c, i) {
        return p + c*result[i];
      }, 0);
      if (s <= 150) return '股市弄潮儿';
      else if (s <= 220) return '假装在投资';
      else if (s <= 270) return '奥马哈之雾';
      else return '说中文的巴菲特';
    },
    isSnowBrick:function(){
      return navigator.userAgent.match(/SnowBrick/i)
    },
    callBrick:function(parameters) {
      if (!SNB.Util.isSnowBrick()) {
        return false;
      }
      var iframe = document.createElement('iframe');
      iframe.setAttribute('src', 'js:' + encodeURIComponent(JSON.stringify(parameters)));
      document.documentElement.appendChild(iframe);
      iframe.parentNode.removeChild(iframe);
      iframe = null;
    },
    getAccessToken:function() {
      return $.cookie("xq_a_token") || SNB.data.access_token
    },
    decimal_2: function(decimal) {
      if(!decimal){//TODO
        return "-";
      }
      var f_x = parseFloat(decimal);
      var readable = ["", "万", "亿"];
      var index = 0;
      while (decimal > 10000 && index < 2) {
        decimal /= 10000;
        index ++;
      }
      f_x = Math.round(decimal*100)/100;
      var s_x = f_x.toString();
      var pos_decimal = s_x.indexOf('.');
      if (pos_decimal < 0) {
        pos_decimal = s_x.length;
        s_x += '.';
      }
      while (s_x.length <= pos_decimal + 2) {
        s_x += '0';
      }
      return s_x + readable[index];
    },
    decimal_2_noparse:function(decimal,isB){//如果是沪B的话原样返回
      if(typeof decimal==="undefined"||decimal===""){//TODO
        return "-";
      }
      if(isB){
        return decimal;
      }
      var f_x = parseFloat(decimal);
      if(f_x>0&&f_x<1){
        return f_x.toFixed(3);
      }else if(f_x>=1||f_x<=0){
        return f_x.toFixed(2);
      }
      return decimal;
    },
    upStock: function(change) {
      if(_.isUndefined(change)){
        return "-";
      }
      change = Number(change);
      var changeString = ( Math.round(change*100)/100 ).toString();
      var pos_decimal = changeString.indexOf(".");
      if (pos_decimal < 0 ) {
        pos_decimal = changeString.length;
        changeString += ".";
      }
      while (changeString.length <= pos_decimal + 2) {
        changeString += "0";
      }
      return change > 0 ? "+" + changeString : changeString;
    },
    upDownClass: function(quote) {
      quote = Number(quote);
      if (quote > 0) {
        return "stock_up";
      } else if (quote < 0) {
        return "stock_down";
      }
      return "";
    },
    getStockInfo:function(stockid){
      var specialHKStocks={
          HKHSI:1,
          HKHSF:1,
          HKHSU:1,
          HKHSP:1,
          HKHSC:1,
          HKVHSI:1,
          HKHSCEI:1,
          HKHSCCI:1,
          HKGEM:1,
          HKHKL:1
        },
        USIndexes={
          DJI30:1,
          NASDAQ:1,
          SP500:1,
          ICS30:1,
          SLR10:1,
          TMT20:1,
          HCP10:1,
          EDU10:1
        },
        bitcoins={
          BTCNCNY:{
            money:"￥",
            market:"比特币（CNY）"
          },
          MTGOXAUD:{
            money:"AU$",
            market:"比特币（AUD）"
          },
          MTGOXCNY:{
            money:"￥",
            market:"比特币（CNY）"
          },
          MTGOXEUR:{
            money:"€",
            market:"比特币（EUR）"
          },
          MTGOXGBP:{
            money:"£",
            market:"比特币（GBP）"
          },
          MTGOXJPY:{
            money:"J￥",
            market:"比特币（JPY）"
          },
          MTGOXUSD:{
            money:"$",
            market:"比特币（USD）"
          }
        },
        fundSymbolArray=["SH500","SH510","SH511","SH513","SZ15","SZ18","SZ16"],
        stockInfo;

      if(stockid&&(~_.indexOf(fundSymbolArray,stockid.substr(0,5))||~_.indexOf(fundSymbolArray,stockid.substr(0,4)))){
        stockInfo={money:"￥",market:"",bigType:"基金",type:"基金"};
      }else if(/^S[HZ]\d+$/.test(stockid)){
        if(/^SZ200/.test(stockid)){//SH900||SZ200为HK$B股
          stockInfo={money:"HK$",market:"深B",bigType:"沪深",type:"股票"}
        }else if(/^(SH(201|202|203|204|131)|SZ(13|395032))/.test(stockid)){
          // 回购
          stockInfo={money:"￥",market:"回购",bigType:"沪深",type:"回购"}
        }else if(/^(SH(01|02|13)|SZ(10|09))/.test(stockid)){
          // 国债
          stockInfo={money:"￥",market:"国债",bigType:"沪深",type:"国债"}
        }else if(/^(SH12|SZ11)/.test(stockid)){
          // 企债
          stockInfo={money:"￥",market:"企债",bigType:"沪深",type:"企债"}
        }else if(/^(SH11|SZ12)/i.test(stockid)){
          // 可转债 
          stockInfo={money:"￥",market:"可转债",bigType:"沪深",type:"可转债"}
        }else if(/^SH900/.test(stockid)){
          stockInfo={money:"$",market:"沪B",bigType:"沪深",type:"股票"};
        }else if(/^(SH00|SZ399)/.test(stockid)){//指数
          stockInfo={money:"",market:"",bigType:"指数",type:"指数"};
        }else{
          stockInfo={money:"￥",market:"A股",bigType:"沪深",type:"股票"};
        }
      }else if(/^\d+$/.test(stockid)){
        stockInfo={money:/^8/.test(stockid)?"￥":"HK$",market:"港股",bigType:"港股",type:"股票"};
      }else if(specialHKStocks[stockid]||USIndexes[stockid]){//指数
        stockInfo={money:"",market:"",bigType:"指数",type:"指数"};
      }else{
        var bitcoin=bitcoins[stockid];
        if(bitcoin){
          stockInfo={money:bitcoin.money,market:bitcoin.market,bigType:"比特币",type:"比特币"};
        }else{
          stockInfo={money:"$",market:"美股",bigType:"美股",type:"股票"};
        }
      }
      return stockInfo;
    },
    parseTime: function(time, render) {
      var curTime = new Date();
      var fromTime;

      if (typeof time === 'object') {
        fromTime = time;
      } else {
        time = typeof render == 'function' ? render(time) : time

        fromTime = new Date()
        fromTime.setTime(time)
        if (fromTime == 'Invalid Date') {
          fromTime.setTime(parseInt(time))
        }
      }



      var beforeSeconds = (curTime.getTime() - fromTime.getTime()) / 1000;
      var format, day, h, m, month;
      month = fromTime.getFullMonth();
      day = fromTime.getFullDate();
      h = fromTime.getFullHours();
      m = fromTime.getFullMinutes();

      if (curTime.getYear() != fromTime.getYear()) {
        format = fromTime.getFullYear() + '-' + month + '-' + day + ' ' + h + ':' + m;
      } else if (curTime.getMonth() != fromTime.getMonth() || curTime.getDate() != fromTime.getDate()) {
        format = month + '-' + day + ' ' + h + ':' + m;
      } else if (beforeSeconds < 60) {
        beforeSeconds = beforeSeconds < 3 ? 3: beforeSeconds;
        format = Math.ceil(beforeSeconds) + '秒前';
      } else if (beforeSeconds < 3600) {
        format = Math.ceil(beforeSeconds / 60) + '分钟前';
      } else {
        format = '今天 ' + h + ':' + m;
      }
      return format;
    },
    getTimestamp: Date.now || function(){
      return new Date().getTime()
    },
    pdfLink: function ($fv, href) {
      var pdf = $fv.data('pdf')
        , $div = $('<div class="zoom-pdf-box"></div>')
      if (pdf && !$fv.next().is('div.zoom-pdf-box')) {
        $div.append('<a class="zoom" href="' + href + '/pdf' +
          '" target="_blank"><i></i><span>全屏查看</span></a>')
        $div.append('<a class="zoom download" target="_blank" ' +
          'href="/stockreport/download?name=' + pdf +
          '" target="_blank" data-toggle="download"><i></i><span>下载查看</span></a>')
        $fv.after($div)
      }
    },
    statusPdf: function (status) {
      if (status.retweeted_status) return status
      var pdfLinkReg = /<a href=['"]?(http:\/\/(xqdoc.b0.upaiyun.com|doc.xueqiu.com)\/([^'"\s]+)\.pdf)['"\s][^>]*>[^<]+<\/a>$/i
      status.pdfRemovedContent = status.text.replace(pdfLinkReg, function (all, p1, p2, p3) {
        status.pdfLink = p1
        status.pdf = p3
        return ''
      })
      status.description = status.description.replace(pdfLinkReg, '')
      return status
    },
    showTip: function (name, $tip, $close) {
      var store = SNB.store || require('./lib/store')
        , tipStatus = store.get('tip:' + name)
        , setShow = function () {
            store.set('tip:' + name, 's')
            if (!SNB.currentUser.isGuest) SNB.get('/tips/status/update.json', { source: name, status: 's' })
          }
        , setHide = function () {
            store.set('tip:' + name, 'h')
            if (!SNB.currentUser.isGuest) SNB.get('/tips/status/update.json', { source: name, status: 'h' })
          }
      $tip.hide()
      $tip.data('setShow', setShow)
      $tip.data('setHide', setHide)
      if (!tipStatus) {
        if (SNB.currentUser.isGuest) {
          tipStatus = 's'
        } else {
          SNB.get('/tips/status/show.json?source=' + name, function (data) {
            var s = data.tips_statuses
            if (s.length && s[0].status != 's') {
              tipStatus = 'h'
            } else {
              tipStatus = 's'
            }
            store.set('tip:' + name, tipStatus)
          })
        }
        showTip(tipStatus)
      } else showTip(tipStatus)
      function showTip (showOrHide) {
        if (showOrHide !== 's') return
        $tip.fadeIn()
        $close.off('click.closeTip').on('click.closeTip', function (ev) {
          $tip.fadeOut()
          setHide()
        })
      }
    },
    pdfFullscreenHint: function ($fv) {
      if (!$fv || !$fv.length) return
      $fv.findOrAppend('.fullscreen-hint', '<div class="fullscreen-hint dropdown-menu"><span>提示：点击此处以全屏模式查看</span><span class="close-button">X</span></div>', function ($fh) {
        SNB.Util.showTip('pdf_fullscreen', $fh, $fh.find('.close-button'))
      })
    },
    pdfViewer: function (id, pdfFileName) {
      seajs.use(['flexpaper.js', 'flexpaper_handlers.js'], function () {
        var $fp = $('#' + id)
        $fp.FlexPaperViewer({
            config : {
            SWFFile : 'http://xqdoc.b0.upaiyun.com/' + pdfFileName + '.swf',
            key : "$ffc627e4203219a906c",

            Scale : 0.6,
            ZoomTransition : 'easeOut',
            ZoomTime : 0.5,
            ZoomInterval : 0.2,
            FitPageOnLoad : false,
            FitWidthOnLoad : true,
            PrintEnabled : false,
            FullScreenAsMaxWindow : false,
            ProgressiveLoading : true,
            MinZoomSize : 0.2,
            MaxZoomSize : 5,
            SearchMatchAll : false,
            InitViewMode : 'Portrait',
            RenderingOrder : 'flash,html',
            StartAtPage : '',

            ViewModeToolsVisible : false,
            ZoomToolsVisible : true,
            NavToolsVisible : true,
            CursorToolsVisible : false,
            SearchToolsVisible : false,
            WMode : 'opaque',
            localeChain: 'zh_CN'
          }}
        );
        var $m = $fp.siblings('.flexpaper_mask')
        if (!$m.length) return
        var $loaded = $m.find('.fp_loaded')
          , $total = $m.find('.fp_total')
          , show = function () {
              if ($fp.data('mask_removed')) return
              $fp.data('mask_removed', true)
              setTimeout(function () {
                $loaded.text('0%')
                $m.find('.flexpaper_hint').hide()
                $m.fadeOut(function () {
                  $fp.data('mask', $m.detach())
                })
              }, 800)
            }
          , ratio
        $fp.data('show', show)
        $fp.on('onProgress', function (ev, loaded, total) {
          loaded = parseInt(loaded, 10)
          total = parseInt(total, 10)
          ratio = loaded / total * 100 | 0
          if (ratio > 95) show()
          $loaded.text(ratio + '%')
        })
        $fp.on('onDocumentLoaded onCurrentPageChanged', show)
        setTimeout(function () {
          if (!ratio) show()
        }, 3000)
        SNB.Util.pdfFullscreenHint($fp.parent())
      })
    },
    parseContent: function(content, pasted, leadingSpace) {
      content = (content || '')
                  .replace(/<!--.*?-->|&lt;!--.*?--&gt;/g, '')
                  .replace(/\uF0A7|\uF020/g, '') //pdf 粘贴过来的非法字符
                  .replace(/\uFEFF|\u200B/g, '') //ueditor 使用的空白字符
                  .replace(/<\/?wbr[^>]*>|<\/?o:p[^>]*>|<\/?font[^>]*>|<\/?st1:[^>]*>|<\/?i(?!m)[^>]*>/gi, '') //删除不支持的标签
                  .replace(/<style[^>]*>[\s\S]*?<\/style>|&lt;style.*?&gt;[\s\S]*?&lt;\/style&gt;/gi, '') //删除style标签
                  .replace(/\n/g, '\r')
                  .replace(/<\/tr*>/ig, '<\/tr>\n')
                  .replace(/<br[^>]*>/ig, '\n')
                  .replace(/<\/p>/ig, pasted ? '\n\n' : '\n')
                  .replace(/([\u0020\u00a0\t\r]|&nbsp;)*<p[^>]*>|\r/gi, '')
                  .replace(/^[\s\u00a0]+|([\s\u00a0]|&nbsp;)+$/gi, '')
                  .replace(/([\u0020\u00a0]|&nbsp;)+(?=\n)/gi, '')
      if (!leadingSpace) content = content.replace(/^([\s\u00a0]|&nbsp;)+/gi, '');
      if (pasted) content = content.replace(/\n{2,}/g, '<br><br>')
                    .replace(/<\/?strong[^>]*>/gi, '') // paste 时在这里过滤 strong
      content = content
                  .replace(/\n/g, '<br>')
                  .replace(/\u200B<img/g, '<img') //解决IE图片点击bug的空字符
                  .replace(/<span([^>]*)>([\s\S]*?)<\/span>/gi, function(all, attrs, inner) {
                    if (pasted) {
                      return attrs.match(/_ie_paste_/i) ? all : inner
                    }
                    if (attrs.match(/_baidu_bookmark_/i)) return all //保留百度书签 span，否则会在主编辑器初始化时出错
                    if (attrs.match(/highlight/i)) return all //保留highlight，否则会在搜索页无法出现高亮关键字
                    var matched = attrs.match(/text-decoration:\s*underline/i)
                    return matched ? '<span style="text-decoration: underline;">' + inner + '</span>' : inner
                  })
                  .replace(/([^>\s])((?:&nbsp;)+)/g, function(all, s1, s2) { return s1 + ' ' + s2.substring(6) })
      return content
    },
    reparseContent: function(content) {
      content = content || ''
      var faceReg = /<img[^>]+src=('|")http:\/\/js\.xueqiu\.com\/images\/face\/([^>]+)\.png\1[^>]*\/?>/ig,
      lazyImgReg = /<img[^>]+data-image="([^"]+)"[^>]*>/ig,
      linkReg = /<\/?a[^>]*>/ig,
      //替换A标签
      content = content.replace(linkReg, "");
      //face
      content = content.replace(faceReg, function(all, first, second) {
        var result;
        if ((result = SNB.Util.BBCODE_TO_TEXT[second])) return result
        else return all
      });
      //lazy loading images
      content = content.replace(lazyImgReg, '<img class="ke_img" src="$1" />');
      return content;
    },
    cleanContent: function(content, keepBookmark, editor, pasted, leadingSpace) {
      content = content || ''
      if (editor) {
        if (window.UE) content = UE.pasteFilter(content, editor)
        if (editor.ta && !editor.ta.$uew.parent().is('.editor, .editor-wrapper')) //非主编辑器去掉图片
          content = content.replace(/<img([^>]+)>/gi, '')
      }
      content = SNB.Util.parseContent(content, pasted, leadingSpace)
      var $el = $('<div>'+content+'</div>')
      if (!$.trim($el.text()).length && !$el.find('img').length) return ''

      if (!keepBookmark)
        $el.find('span').each(function(i, el) {
          if (/^_baidu_bookmark_/.test(el.id)) $(el).remove()
        }) // 正常应该不存在书签 span，以防万一
      $el.find('img.ke_img_paste').remove()
      $el.find('img.ke_img[src*=".xueqiu.com/images/blank.png"]').remove()
      content = $el.html()

      var reg = /<img[^>]+class="?ke_img[^>]*>/ig
      content = content.replace(reg, function(all) {
        var matched = all.match(/src="?([^"\s]+)/i)
        if (matched) return '<img class="ke_img" src="' + matched[1] + '" />'
        else return all
      })

      content = content.replace(/<([uo]l)([^>]*)>/ig, function(all, tag, attr) {
        var match
        if ( (match = attr.match(/style="[^"]+"/)) ) {
          return '<'+tag+' '+match[0]+'>'
        }
        return '<'+tag+'>'
      }) //数据出现 <ul ... /> 的bug
      return content
    },
    isContentSame: function(a, b) {
      a = a.replace(/\s|\u00a0|\u0020|&nbsp;/g, '')
      b = b.replace(/\s|\u00a0|\u0020|&nbsp;/g, '')
      return a == b
    },
    htmlizeContent: function(content) {
      content = content || ''
      content = content.replace(/\r\n?|\n/g, '<br>')
      content = content.replace(/&lt;|&amp;|&quot;|&gt;/g,function(m){
         return {
           '&lt;': '<',
           '&amp;': '&',
           '&quot;': '"',
           '&gt;': '>'
         }[m]
      })
      return content
    },
    unhtml:function(str) {
      return str ? str.replace(/[&<">]/g, function(m){
        return {
           '<': '&lt;',
           '&': '&amp;',
           '"': '&quot;',
           '>': '&gt;'
        }[m]
      }) : '';
    },
    updateCount: function (content, option) {
      var reg = /\d+/ig;
      if (reg.test(content)) {
        content = content.replace(reg, function (all) {
          if (option < 0) {
            return parseInt(all) - 1;
          } else {
            return parseInt(all) + 1;
          }
        });
      } else {
        content += "(1)";
      }
      return content;
    },
    getWordsCount: function(content) {
      var chars = content.split('');
      var count = 0;
      $(chars).each(function() {
        if (this.charCodeAt(0) < 256) {
          count++;
        }
      });
      var unic = content.length - count;
      return unic + Math.round(count / 2);
    },
    splitWord:function(content,length){
      if(content&&content.length>length){
        var count=0,
            index=0,
            chars=content.split('');

        for(var i=0,len=chars.length;i<len;i++){
          var cha=chars[i];
          if(cha.charCodeAt(0)<256){
            count+=0.5;
          }else{
            count+=1;
          }
          if(count>length){
            return content.substr(0,index);
          }
          index++;
        }
      }
      return content;
    },

    splitWordWithElipse:function(str,length){
      var len=length||4;
      if(this.getWordsCount(str)>len){
        return this.splitWord(str,len)+"...";
      }else{
        return str;
      }
    },
    getWindowSize: function(options){
      var screenX = typeof window.screenX != 'undefined' ? window.screenX: window.screenLeft,
          screenY = typeof window.screenY != 'undefined' ? window.screenY: window.screenTop,
          outerWidth = typeof window.outerWidth != 'undefined' ? window.outerWidth: document.documentElement.clientWidth,
          outerHeight = typeof window.outerHeight != 'undefined' ? window.outerHeight: (document.documentElement.clientHeight - 22),
          width = typeof options !== "undefined" && typeof options.width !== "undefined"? options.width : 580,
          height = typeof options !== "undefined" && typeof options.height !== "undefined"? options.height : 355,
          left = parseInt(screenX + ((outerWidth - width) / 2), 10),
          top = parseInt(screenY + ((outerHeight - height) / 2.5), 10),
          features = ('width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + ',toolbar=no,menubar=no,scrollbars=no,   resizable=no,location=no,status=no');
      return features;
    },
    dialog_vertical_middle:function(ui_dialog){
      var dialogHeight = ui_dialog.height(),
          docElem = document.documentElement,
          top = 0,
          clientHeight = docElem.clientHeight;
      top = clientHeight > dialogHeight && (clientHeight - dialogHeight) / 2;
      ui_dialog.css("top",top + $(document).scrollTop())
    },
    checkLogin:function(callback){//new checkLogin
      if(SNB.data.is_brick) return
      var that = this,
          show_dialog = function(){
            SNB.Guest.showLoginDialog(function(){
              if(callback){
                callback();
              }
            });
          }
      if(SNB.currentUser.isGuest){
        if(typeof SNB.Guest !== "undefined"){
          show_dialog()
        }else{
          seajs.use("SNB.guest.js",function(){
            show_dialog()
          })
        }
      }else{
        if(callback){
          callback();
        }
      }
    },
    insertStockAutocompletionOptions: {
      source: function(request, response){
        SNB.get("/stock/search.json", {size: 10, code: request.term}, function(data) {
          response($.map(data.stocks, function(stock){
            return {
              label: stock.name + "(" + stock.code + ")",
              name: stock.name,
              value: stock.code
            }
          }));
        })
      },
      autoFocus:true
    },
    insertStock: function (pos, callback) {
      $("#stockbox").remove()

      var dialogInsertStock = $('<div id="stockbox"/>').appendTo("body>.temp")
        , stockboxinput = $('<input type="text" class="stockboxinput" id= "stockboxinput" />').appendTo(dialogInsertStock)

      dialogInsertStock.dialog({
        modal: true,
        stack: true,
        width: "330px",
        minHeight: "54px",
        title: "请输入股票代码/中文名/英文名",
        close: function(){
          stockboxinput.val("");
          stockboxinput.autocomplete("close");
        },
        dragStart: function(){
          stockboxinput.autocomplete("close");
        },
        dragStop: function(){
          stockboxinput.autocomplete("search");
        },
        position: pos
      });

      stockboxinput.autocomplete(SNB.Util.insertStockAutocompletionOptions);

      stockboxinput.bind("autocompleteselect", function(event, ui){
        if (callback) {
          callback(ui.item);
        }
        dialogInsertStock.dialog("close");
      });
    },
    deleteDialog:function(elm,callback){
      var $target = $(elm),
          deleteDialog_html = "",
          deleteDialog = $("#dialog-delete"),
          canBlock = $target.attr("canBlock"),
          blockUserId = $target.attr("blockUserId");
      if(canBlock){
        deleteDialog_html =   '<p class="dialog-msg hasBlock">确定删除这条评论吗？</p>'
                              + "<div class='block'><input type='checkbox' name='block' id='block_user'></input><label for='block_user'>将对方拉黑</label></div>"
                              + '<div>'
                                + '<input type="button" class="submit ok" value="确定"/>'
                                + '<input type="button" class="button cancel" value="取消"/>'
                              + '</div>';
      }else{
        deleteDialog_html =   '<p class="dialog-msg">确定删除这条评论吗？</p>'
                              + '<div>'
                                + '<input type="button" class="submit ok" value="确定"/>'
                                + '<input type="button" class="button cancel" value="取消"/>'
                              + '</div>';
      }

      if(deleteDialog.length===0){
        $("body").append('<div id="dialog-delete" class="dialog-wrapper">'+deleteDialog_html+"</div>");
      }else{
        $("#dialog-delete").html(deleteDialog_html);
      }

      deleteDialog = $("#dialog-delete");
      deleteDialog.find(".cancel").click(function(){
        deleteDialog.dialog("close");
      })
      deleteDialog.find(".submit").unbind("click").click(function () {
        deleteDialog.dialog("close");
        if(deleteDialog.find("input#block_user").is(":checked")){
          SNB.post("/blocks/create.json",{user_id:blockUserId},function(){
          })
        }
        if (callback) {
          callback();
        }
      });
      return deleteDialog;
    },
    confirmDialog:function(msg,callback){
      var confirmDialog = $("#dialog-confirm");
      if (confirmDialog.length < 1) {
        var html = '<div id="dialog-confirm" class="dialog-wrapper">'
            + '<p  class="dialog-msg">' + msg + '</p>'
            + '<p style="width:100%;text-align:center;">'
              + '<input type="button" class="submit" value="确定"/>'
              + '<input type="button" class="cancel button" value="取消"/>'
            + '</p>'
          + '</div>';
        $("body").append(html);
        confirmDialog = $("#dialog-confirm");

        confirmDialog.find(".cancel").click(function(){
          confirmDialog.dialog("close");
        })
      }
      confirmDialog.find(".dialog-msg").html(msg);
      confirmDialog.find(".submit").unbind("click").click(function () {
        confirmDialog.dialog("close");
        if (callback) {
          callback();
        }
      });
      return confirmDialog;
    },
    stateDialog:function(msg,timeout,callback,modal,width,position,minWidth){
      var savedDialog = $("#dialog-saved-success"),
          _modal = typeof modal !== "undefined"  ? modal : true,
          _width = typeof width !== "undefined"  ? width : 200,
          _minWidth = typeof minWidth !== "undefined"  ? minWidth : 150,
          _position = typeof position !== "undefined"  ? position : ["center","center"];
      if (savedDialog.length < 1) {
        var html = '<div id="dialog-saved-success" class="dialog-wrapper"><span class="savedsuccesstip">' + msg + '</span></div>';
        $("body").append(html);
        savedDialog = $("#dialog-saved-success");
      }
      if(_minWidth < 150){
        savedDialog.addClass("lite-content");
      }
      savedDialog.find(".savedsuccesstip").html(msg);
      savedDialog.dialog({ modal: _modal, width: _width, minHeight: 20 ,position: _position,minWidth: _minWidth}).prev().hide();
      setTimeout(function () { savedDialog.dialog("close");if(callback){ callback(); }}, timeout || 2000);
      return savedDialog;
    },
    failDialog: function(msg, width, callback,timeout) {
      var failDialog = $("#dialog-failed");
      if (failDialog.length < 1) {
        var html = '<div id="dialog-failed" class="dialog-wrapper"><s class="info"></s><span class="savedfailtip"></span></div>';
        $("body").append(html);
        failDialog = $("#dialog-failed");
      }
      failDialog.find(".savedfailtip").text(msg);
      failDialog.dialog({ modal: true, width: width || 200, minHeight: 50 }).prev().hide();
      setTimeout(function () {
        failDialog.dialog("close");
        if (callback) {callback()}
      }, timeout || 1000);
    },
    reportSpam: function(options,callback){
      SNB.Util.checkLogin(function(){
        require.async("SNB.reportSpam.js",function(exports){
          exports.reportSpam(options,callback);
        })
      })
    },
    getShareInfo:function(cb){
      SNB.data.is_bind = false;
      SNB.data.qq_bind = false;
      SNB.data.sina_bind = false;
      SNB.Util.checkLogin(function(){
        SNB.get("/account/oauth/show.json",{},function(ret){
          if (typeof ret !== 'object') {
            ret = $.parseJSON(ret);
          }
          var oauthdata = ret.oauthbind,
              oauthdata_length = oauthdata.length;
          if(oauthdata_length){
            _.forEach(oauthdata,function(index,value){
              if(oauthdata[value][0] == "qq"){
                SNB.data.qq_bind = true;
                SNB.data.qq_expireIn = oauthdata[value][3];
                SNB.data.qq_accessToken = oauthdata[value][1];
                SNB.data.is_bind = true;
              }else if(oauthdata[value][0] == "sina"){
                SNB.data.sina_expireIn = oauthdata[value][3];
                SNB.data.sina_bind = true;
                SNB.data.is_bind = true;
              }
            })
          }
          if(cb){
            cb();
          }
        })
      })
    },
    shareDialog: function(status,callback){
      SNB.Util.getShareInfo(function(){
        require.async("SNB.shareDialog.js",function(exports){
          if(typeof status.canEdit !== "undefined"){
            exports.shareStatus(status,callback);
          }else{
            exports.shareMsg(status,callback)
          }
        })
      })
    },
    shareModule:function(options){
      SNB.Util.getShareInfo(function(){
        require.async("SNB.portfolioShareDialog.js",function(share){
          var portfolioShare=share.portfolioShare;
          var p=SNB.data.share=new portfolioShare(options);
        })
      })
    },
    addFriend:function(user,callback,traceId){
      var that=this,
          id=user.id,
          url="/friendships/create.json"

      if(traceId){
        url+="?trace_id="+traceId;
      }

      SNB.post(url, {id: id}, function(data){
        if (data.success) {
          if(callback){
            callback();
          }
          var d=SNB.dialog.userGroup(user,true);
          if(d){
            d.dialog({
              title:"关注成功",
              width:"360px",
              modal:true
            });
          }
        } else {
          SNB.Util.failDialog(data.message,220);
        }
      },function(ret){
        SNB.Util.addFriend_errorCallback(ret)
      })
    },
    addFriend_errorCallback:function(ret){
      var ret_error_code = ret && ret.error_code,
          ret_error_desc = ret && ret.error_description || "关注出错，请稍后重试";
      if(ret_error_code === "22801"){
        if($(".addfri_dialog_full").length){
          $(".addfri_dialog_full").dialog();
          return
        }
        var $addfri_dialog_full = $("<div class='addfri_dialog_full'>"),
            template = require("./dialog-with-buttonLink.jade")({desc:"你今天已新增关注了50人，绑定微博还能查找到好友",a_href:"/people",a_text:"去绑定微博"})
        $addfri_dialog_full.append(template).dialog({width:210, minHeight:70, modal:true}).prev().hide()
        $addfri_dialog_full.on("click",".cancel",function(){
          $addfri_dialog_full.dialog("close");
        })
      }else{
        SNB.Util.failDialog(ret_error_desc,220,function(){},2000)
      }
    },
    removeFriend:function(id,callback){
      SNB.post("/friendships/destroy/"+id+".json", callback, function(){
        SNB.Util.failDialog('取消关注失败');
      })
    },
    verifyEmail:function(email,callback){
      SNB.get("/account/verify_email.json",{
          email: email
        },callback);
    },
    getEmailService: function(email){
      var emailService="";
      if (email.search("@sina.com")!=-1 || email.search("@vip.sina.com")!=-1 || email.search("@sina.cn")!=-1) {
        emailService =  "http://mail.sina.com.cn/";
      } else if (email.search("@sohu.com")!=-1) {
        emailService =  "http://mail.sohu.com";
      } else if (email.search("@yahoo.com.cn")!=-1 || email.search("@yahoo.cn")!=-1) {
        emailService =  "http://mail.cn.yahoo.com";
      } else if (email.search("@yahoo.cn")!=-1) {
        emailService =  "http://mail.cn.yahoo.com";
      } else if (email.search("@qq.com")!=-1 || email.search("@vip.qq.com")!=-1 || email.search("@foxmail.com")!=-1) {
        emailService =  "http://mail.qq.com";
      } else if (email.search("@hotmail.com")!=-1 || email.search("@msn.com")!=-1 || email.search("@live.com")!=-1) {
        emailService =  "http://www.hotmail.com";
      } else if (email.search("@gmail.com")!=-1) {
        emailService =  "http://mail.google.com";
      } else if (email.search("@139.com")!=-1) {
        emailService =  "http://mail.10086.cn/";
      } else if (email.search("@21cn.com")!=-1 || email.search("@21cn.net")!=-1) {
        emailService =  "http://mail.21cn.com";
      } else if (email.search("@tom.com")!=-1 || email.search("@vip.tom.com")!=-1 || email.search("163.net")!=-1) {
        emailService =  "http://mail.tom.com";
      } else if (email.search("@163.com")!=-1) {
        emailService =  "http://mail.163.com";
      } else if (email.search("@126.com")!=-1) {
        emailService = "http://mail.126.com/";
      } else if (email.search("@yeah.net")!=-1) {
        emailService = "http://www.yeah.net/";
      } else if (email.search("@sogou.com")!=-1) {
        emailService = "http://mail.sogou.com/";
      } else if(email.search("@189.cn")!=-1) {
        emailService = "http://webmail17.189.cn/webmail/";
      } else if(email.search("@eyou.com")!=-1) {
        emailService = "http://www.eyou.com/";
      } else if(email.search("@188.com")!=-1) {
        emailService = "http://www.188.com/";
      } else if(email.search("@wo.com.cn")!=-1) {
        emailService = "http://mail.wo.com";
      }
      return emailService;
    },
    activate_send_email:function(email,callback,type){
      var url = typeof type !== "undefined" && type === "modify_email" ? "/account/activate_send_newemail.json" : "/account/activate_send_email.json";
      SNB.post(url,{email:email},function(ret){
        if(callback){
          callback()
        }else{
          SNB.Util.stateDialog("激活邮件已重发，请登录邮箱确认")
        }
      },function(ret){
        SNB.Util.failDialog(ret.error_description);
      })
    },
    oauth_bind_verify:function(data_obj){
      seajs.use("SNB.bind_verify.js",function(){
        SNB.bind.bind_verify(data_obj);
      })
    },
    parseDate:function(input){
      var parts = input.match(/(\d+)/g);
      return new Date(parts[0], parts[1]-1, parts[2]);
    },
    scrollTop:function(className,options){
      var top = typeof options === "object" && typeof options.top !== "undefined" ? options.top : 40;
      var offset_top = $(className).offset().top;
      offset_top = offset_top - top
      $(window).scrollTop(offset_top);
    },
    portfolio_addstock:function(data,callback,error_callback){
      SNB.post("/stock/portfolio/addstock.json",data,function(ret){
        callback && callback(ret)
      },function(ret){
        var ret_error_code = ret && ret.error_code,
            ret_error_desc = ret && ret.error_description || "添加股票出错，请稍后重试";
        if(ret_error_code === "22804"){
          if($(".addStock_dialog_full").length){
            $(".addStock_dialog_full").dialog();
            return
          }
          var $addStock_dialog_full = $("<div class='addStock_dialog_full'>"),
              template = require("./dialog-with-buttonLink.jade")({desc:"你今天已新增关注了10只股票，下载客户端可随时获取行情变化 ",a_href:"/about/mobile-xueqiu",a_text:"了解详情"})
          $addStock_dialog_full.append(template).dialog({width:220, minHeight:70, modal:true}).prev().hide()
          $addStock_dialog_full.on("click",".cancel",function(){
            $addStock_dialog_full.dialog("close");
          })
        }else{
          SNB.Util.failDialog(ret_error_desc,220,function(){},2000)
        }
        error_callback && error_callback(ret)
      })
    },
    saveConfig:function(option){
      if (!SNB.Util.getAccessToken()) return
      var typeList=[],
          valueList=[];

      for(var key in option){
        typeList.push(key);
        valueList.push(option[key]);
        if(key=="timeline_source"){
          $.cookie("source",null);
        }else{
          if(key.indexOf("portfolio")==0){
            $.cookie(key.replace("portfolio_",""),null);
          }
        }
      }
      SNB.get("/user/setting/set_select.json",{type:typeList+"",value:valueList+""},function(ret){});
    },
    getConfig:function(cNames,callback){
      SNB.get("/user/setting/select.json",{types:cNames.toString()},function(ret){
        callback(ret);
      })
    },
    autoCompleteSearchStock:function($el,callback){
      $el.autocomplete({
        source: function(request, response) {
          SNB.get("/stock/search.json", {size: 10, code: request.term}, function(data) {
            response( $.map(data.stocks, function(stock) {
              if(SNB&&SNB.stocksSearch){
                SNB.stocksSearch[stock.code] = stock;
              }
              return {
                label: stock.name + "(" + stock.code + ")",
                name: stock.name,
                value: stock.code
              }
            }));
          });
        },
        select: function(event, ui) {
          var code=ui.item.value,
              name=ui.item.name;

          if(callback){
            callback(code,name);
          }
        },
        autoFocus:true
      });
    },
    formatTime:function(ts){
      var months={
        Jan:"01",
        Feb:"02",
        Mar:"03",
        Apr:"04",
        May:"05",
        Jun:"06",
        Jul:"07",
        Aug:"08",
        Sep:"09",
        Oct:"10",
        Nov:"11",
        Dec:"12"
      };

      var dateStr=_.isNumber(ts)?new Date(ts).toString():ts,
          arr=dateStr.split(" ");

      if(arr[2].length==1){
        arr[2]="0"+arr[2];
      }
      if(arr[3]&&/\d{4}/.test(arr[3])){
        return [arr[3],months[arr[1]],arr[2]].join("-");
      }else{
        return [arr[5],months[arr[1]],arr[2]].join("-");
      }
    },
    redirectToIndex:function($count,count){
      setTimeout(_.bind(function c(count){
        if (--count > 0) {
          $count.html(count);
          setTimeout(_.bind(c, null, count), 1000)
        } else {
          window.location.href = "/?_=" + SNB.Util.getTimestamp();
        }
      }, null, count), 1000)
    },
    updateStatus:function(data,callback,error_callback){
      SNB.post("/statuses/update.json",data,function(ret){
        callback && callback(ret)
      },function(ret){
        if(ret.error_code){
          SNB.Util.failDialog(ret.error_description);
        }else{
          SNB.Util.failDialog("服务器出错，请重试。");
        }
        error_callback && error_callback(ret)
      })
    },
    getDesc:function(user){
      return user.recommend || user.verified_description || user.description || ""
    },
    calculateTs:function(ts,specialTime){
      var specialTimeStr=new Date(ts).toString();
      specialTimeStr=specialTimeStr.replace(/\d+:\d+:\d+/g,specialTime);
      return Date.parse(specialTimeStr);    
    },

    getTradeTime:function(stockType){
      var date=new Date(),
          ts=Date.parse(date),
          timezone=date.getTimezoneOffset(),
          marketTimezone={
            "美股":-4,// 冬令时变成-5
            "港股":8,
            "沪深":8
          },
          timezoneOffset=timezone/60*-1-marketTimezone[stockType],
          tsRelative=ts-timezoneOffset*(60*60*1000),
          date=new Date(tsRelative),
          weekday=date.getDay(),
          marketTradeTime={
            start:SNB.Util.calculateTs(tsRelative,"09:30:00"),
            end:SNB.Util.calculateTs(tsRelative,stockType=="沪深"?"15:05:00":"16:20:00")
          };

      // 周六日直接除去
      if(weekday==0||weekday==6){
        return {phase:"end"};
      }

      if(tsRelative>marketTradeTime.start&&tsRelative<marketTradeTime.end){
        return {phase:"trade"}
      }else{
        if(tsRelative<marketTradeTime.start){
          // 获取距开盘的时间  setTimeout用
          return {phase:"before",ts:marketTradeTime.start-tsRelative};
        }else{
          return {phase:"end"};
        }
      }
    }
  };
  _.each(SNB.Util.BBCODE_MAPPING, function(a) {
    SNB.Util.BBCODE_TO_TEXT[a[0]] = a[1]
    SNB.Util.TEXT_TO_BBCODE[a[1]] = a[0]
  })
  $(function(){
    if(!('placeholder' in document.createElement('input'))){
      $("[placeholder]").live('focus', function() {
        var $input = $(this);
        $input.removeClass("placeholder");
        if ($input.val() == $input.attr("placeholder")) {
          $input.val("");
        }
      }).live('blur', function() {
        var $input = $(this);
        if ($input.val() == "") {
          $input.addClass("placeholder");
          if($input.attr("type")!="password"){
            $input.val($input.attr("placeholder"));
          }else{
            $input.val("");
          }
        }
      }).blur();
      // 避免val取到placeholder值
      var hooks={
        get:function(element){
          var $element = $(element);
          return $element.hasClass('placeholder') ? '' : element.value;
        }
      }
      $.valHooks.input=hooks;
      $.valHooks.textarea=hooks;
    }

    $(".dropdown-menu a.exit").click(function(e) {
      SNB.get("/account/oauth/show.json", function(ret) {
        $.cookie("last_account",ret.email, {path: '/', expires: 90});
        $.cookie("tab",null, {path: "/"});
        $.cookie("xq_a_token",null, {path: "/"});
        $.cookie("xq_r_token",null, {path: "/"});
        $.cookie("order",null, {path: "/"});
        $.cookie("col",null, {path: "/"});
        location.href = "/";
      })
      return false
    });
  });
  //remove useless cookie
  $.cookie("x_nickname",null, {path: "/", domain: ".xueqiu.com"});
  $.cookie("x_passwd",null, {path: "/", domain: ".xueqiu.com"});
  $.cookie("x_token",null, {path: "/", domain: ".xueqiu.com"});
  $.cookie("x_userid",null, {path: "/", domain: ".xueqiu.com"});
  $.cookie("x_tuserid",null, {path: "/", domain: ".xueqiu.com"});
  $.cookie("bbs_auth",null, {path: "/", domain: ".xueqiu.com"});
  $.cookie("bbs_sid",null, {path: "/", domain: ".xueqiu.com"});
  $.cookie("x_userip",null, {path: "/", domain: ".xueqiu.com"});
  $.cookie("__utma",null, {path: "/", domain: ".xueqiu.com"});
  $.cookie("__utmb",null, {path: "/", domain: ".xueqiu.com"});
  $.cookie("__utmc",null, {path: "/", domain: ".xueqiu.com"});
  $.cookie("__utmz",null, {path: "/", domain: ".xueqiu.com"});

  $.cookie("order", null, {path: "/"});
  $.cookie("col", null, {path: "/"});
  $.cookie("__exp_t", null, {path: "/"});
  // login
  $(".nav.account .login,#openLoginDialog").live("click",function(e){
    e.preventDefault();
    SNB.Util.checkLogin(function(){}, e);
  })

  if(typeof $.fn.typeahead !== "undefined"){
    var $typeahead = $(".typeahead");
    $typeahead.typeahead({
      top: 4,
      items: 10,
      match: false,
      sort: false,
      source: function (typeahead, query) {
        var searchText = $.trim($(".typeahead").val());
        if(!searchText) return
        var data = {
          code: searchText.replace(/'/g,""),
          size: 10,
          key:"47bce5c74f"
        };
        return SNB.get("/stock/search.json",data, function (ret) {
          ret = typeof ret !== "object" ? $.parseJSON(ret) : ret
          var stocks = ret.stocks;
          var names = _.pluck(stocks,"name"),
              codes = _.pluck(stocks,"code"),
              arrays = []
          for(var i = 0;i < names.length; i++){
            arrays.push(names[i] + "(" + codes[i] + ")" )
          }
          return query(arrays);
        });
      },
      _render: function(items,that){
        var $elm = $(".typeahead")
        if($elm.val() === $elm.attr("placeholder") || $.trim($elm.val()) === "") return that.hide();
        items = $(items).map(function (i, item) {
          i = $(that.options.item).attr('data-value', item)
          var data_value = i.attr("data-value"),
              code = data_value.match(/\(([^(]*)\)$/g)
          code = code && code[0].substr(1,code[0].length - 2)
          i.find('a').html(that.highlighter(item)).attr("href","/S/"+code)
          return i[0]
        })
        var $temp = $("<ul>");
        if(items.length){
          $temp.append('<li class="no_menu"><h3 class="stock">股票</h3></li>')
               .append(items)
        }
        $temp.append(
              '<li class="no_menu"><h3 class="content">包含<strong>“'+that.query+'”</strong>的讨论</h3></li>'
              + "<li data-value='"+that.query+"'><a href='/k?q="+encodeURIComponent(that.query)+"'target='_blank'>"+that.query+"</a></li>"
              + '<li class="no_menu"><h3 class="content">包含<strong>“'+that.query+'”</strong>的用户</h3></li>'
              + "<li data-value='"+that.query+"'><a href='/u?q="+encodeURIComponent(that.query)+"'target='_blank'>"+that.query+"</a></li>"
            )
        $temp.find("li:not(.no_menu)").first().addClass('active')
        that.$menu.html($temp.html())
        return that
      },
      _select: function(that){
        var val = that.$menu.find('.active').attr('data-value'),
            url = that.$menu.find('.active a').attr("href")
        if(!url) return that.show()
        window.open(url,"_blank")
      }
    })
  }

  // notification
  var unreadMessagePanel = $('<div class="mentions_block">').html(
    '<div class="mentions_inner">'
    + '<div class="sydinfo list">'
    + "<p class='comments'><span class='count'></span>条新评论，<a class='pjax' href='/comments/'>查看&gt;&gt;</a></p>"
    + "<p class='followers'><span class='count'></span>位新粉丝，<a href='/follows'>查看&gt;&gt;</a></p>"
    + "<p class='dm'><span class='count'></span>条新私信，<a href='/messages'>查看&gt;&gt;</a></p>"
    + "<p class='mentions'><span class='count'></span>条@我的，<a class='pjax' href='/atme'>查看&gt;&gt;</a></p>"
    + "<p class='notices'><span class='count'></span>条新公告，<a href='"+(SNB.currentUser.profile||"/")+"?source=3#notices'>查看&gt;&gt;</a></p>"
    + "<p class='events'><span class='count'></span>个事件提醒，<a href='/calendar'>查看&gt;&gt;</a></p>"
    + '</div><a href="/setting/notice" class="notice_set"><i></i></a></div>').appendTo($("body>.temp"));

  if ($.browser.isPad || $.browser.isMobile) unreadMessagePanel.css("position", "absolute")
  unreadMessagePanel.find(".notices a").on("click",function(e){
    if($("body").attr("id")==="my-home"){
      $('html, body').animate({
          scrollTop: $("#status-box").offset().top-50
      }, 200);
      $(".status-tab").find("li:last a").trigger("click");
      return false;
    }
  })
  var messageList = unreadMessagePanel.find('.list');
  SNB.notification = function() {
    var noMentions = $body.hasClass("noMentions");
    if (!SNB.currentUser.id || noMentions) {
      return;
    }
    SNB.get("/statuses/unread.json", function(ret){
      //delete ret.notices;
      delete ret.user_id;
      // 把事件ID拼进URL
      var events_id=ret.events_id;
      delete ret.events_id;
      if(events_id&&events_id.length){
        // 目前只装载第一个提醒ID
        messageList.find(".events a").attr("href","/calendar#"+events_id[0]);
      }

      messageList.find("p").hide();
      var allCount = 0;
      _.each(ret,function(count,key){
        if(count){
          messageList.find("."+key).show().find('span.count').html(count);
          allCount+=count;
        }
      })
      allCount = typeof allCount === "string" ? parseInt(allCount) : allCount
      if (allCount) {
        showUnreadMessagePanel();
      } else {
        closeUnreadMessagePanel();
      }
    });
  }
  function showUnreadMessagePanel() {
    var scrollTop = $(document).scrollTop();
    unreadMessagePanel.css('right', ($(document).width() - $('.navbar .container').width()) / 2).show();
    return false;
  }

  function closeUnreadMessagePanel() {
    unreadMessagePanel.hide('fast');
    return false;
  }

  SNB.Image = {
    default_30 : "community/default/avatar.png!30x30.png",
    default_50 : "community/default/avatar.png!50x50.png",
    default_180 : "community/default/avatar.png!180x180.png",
    zoomIn:function(imageElm){
      var image_zoomIn = imageElm.attr("src"),
         endIndex = image_zoomIn.indexOf("%21custom.jpg") != -1 ? image_zoomIn.indexOf("%21custom.jpg")  :  image_zoomIn.indexOf("!custom.jpg") ;
      if(endIndex == -1){
        return;
      }
      var image_zoomOut = image_zoomIn.substr(0,endIndex),
         $html = "<a class='zoom' href='"+image_zoomOut+"'target='_blank'><i></i><span>查看原图</span></a>";
      imageElm.next().is('br') && imageElm.next().remove()
      imageElm.after($html);
    },
    lazyload:function(text){
      return text.replace(/<img(.*?)src="?(https?:\/\/xqimg.*?custom.jpg)"?(.*?)\/?>/gi,'<img$1src="http://assets.xueqiu.com/images/blank.png" data-image="$2"$3/>')
    },
    getProfileImage:function(profile_image_url,size){
      profile_image_url = profile_image_url && profile_image_url.split(",") || [];
      var img = SNB.domain.photo + "/" + (profile_image_url.length > 3 ? profile_image_url[3] : (profile_image_url.length == 1 ? profile_image_url[0] : 'community/default/avatar.png!30x30.png'))
      img = typeof size !== "undefined" ? img.replace(/([0-9]+)x([0-9]+)/,size + "x" + size) : img
      return img;
    }
  }
  unreadMessagePanel.find('.closesyd').click(closeUnreadMessagePanel);
  $(function() {
    SNB.notification();
  });
  window.isActive = true;
  setInterval(function(){
    if (window.isActive) {
      SNB.notification()
    }
  }, 60000);
  $(window).focus(function() {
    SNB.notification()
  });
  $(function() {
    $(window).focus(function() {
      window.isActive = true;
    });
    $(window).blur(function() {
      window.isActive = false;
    });
  })

  // 禁用 backspace，避免不小心离开页面
  $doc.on('keydown', function(ev) {
    if (!$(ev.target).is('input, textarea') && ev.keyCode === 8) {
      ev.preventDefault()
    }
  })

  // scroll 事件
  ;(function() {
    var didScroll = true
      , checkScrollInterval = $.browser.msie ? 100 : 50

    SNB.scroll = {}

    var ConditionHandler = SNB.scroll.ConditionHandler = function(condition, handle) {
      var condFunc = ('function' === typeof condition) ? condition : function () { return condition }
      return function(st) {
        if (condFunc()) {
          handle(st)
        }
      }
    }
    var handlers = SNB.scroll.handlers = []

    setTimeout(function doScrollCheck () {
      var st
      if (didScroll) {
        didScroll = false
        st = $win.scrollTop()
        _.each(handlers, function(handler) {
          handler(st)
        })
      }
      setTimeout(doScrollCheck, checkScrollInterval)
    }, checkScrollInterval)

    $win.scroll(function() {
      didScroll = true
    })

    //检查是否是编辑器全屏状态
    var isEditorMode = SNB.scroll.isEditorMode = function() {
          return $body.hasClass('editor-mode') || $body.hasClass('main-editor-mode')
        }
      , isNotEditorMode = SNB.scroll.isNotEditorMode = function() {
          return !isEditorMode()
        }

    //指定各 handler
    /*
     *handlers.push(ConditionHandler(isNotEditorMode, function(st) {
     *  if (st > 0) {
     *    unreadMessagePanel.css('position','fixed');
     *  } else {
     *    unreadMessagePanel.css('position','absolute');
     *  }
     *}))
     */

    /*
    handlers.push(ConditionHandler(isEditorMode, function(st) {
      var $editor = $('.editor:visible')
        , dh = $doc.height()
        , wh = $win.height()
      if (st > 45) $('.editor-toolbar', $editor).addClass('fixed')
      else $('.editor-toolbar', $editor).removeClass('fixed')
      //if (dh - st - wh > 32) $('.editor-footer', $editor).addClass('fixed')
      //else $('.editor-footer', $editor).removeClass('fixed')
    }))
    */

    $(function(){
      $('body#jade-single,body#search,body#my-home,body#my-profile,body#his-profile,body#hots-statuses,body#jade-singleStock,body.scrollToTop').found(function() {
        var $center = $('#center')
          , data_offset_left = parseInt($body.attr("data_offset_left")) || 0
          , $toTop = $('<a href="#" title="回到顶部" id="toTop"></a>')
              .hide()
              .on('click', function(e) {
                e.preventDefault()
                $win.scrollTop(0)
                $toTop.fadeOut(200)
              })
              .appendTo($body)
          , leftOffset = $('body#jade-single').length ? 780 : 740
        handlers.push(ConditionHandler(isNotEditorMode, function(st) {
          if ( st > 1200 )
            $toTop.fadeIn(200);
          else
            $toTop.fadeOut(200);
        }))
        $toTop.css("left", $center.offset().left + leftOffset + data_offset_left);
        window.onresize = function() {
          $toTop.css("left", $center.offset().left + leftOffset + data_offset_left);
        };
      })
    })

  }())

  if (!$body.hasClass('noPreload')) {
    require.async("SNB.editor.js")
    require.async("SNB.repostDialog.js");
    require.async("SNB.downloadDialog.js")
    if ($.browser.isPC) require.async("SNB.tooltip.js");
  }

  //转义IE下@链接
  if ($.browser.msie) {
    $("body").on("click", "a", function(e) {
      var href = $(this).attr("href")
      if (!href || href.substr(0, 2) != '/n/') return
      e.preventDefault()
      window.open('/n/' + encodeURIComponent(href.substr(3)))
    })
  }

/*
 *  var originGetJSON=$.getJSON;
 *  $.getJSON=function(url,params,callback){
 *    var reg=/^\/stock\/portfolio\/((create)|(remove)|(modify)|(modifyorder)|(addstock)|(addstocks)|(delstock)|(updstock)|(addtrans)|(deltrans)|(updtrans))\.json$/i;
 *
 *    if(reg.test(url)){
 *      alert("自选股系统维护中，暂时不能进行操作。");
 *      return false;
 *    }else{
 *      originGetJSON(url,params,callback);
 *    }
 *  }
 */

})($);
})
